package cn.yx.common.web.util;

import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * <p>Spring相关工具类</p>
 *
 * @author Wgssmart
 */
public final class SpringUtil {

    private SpringUtil() {
    }

    /**
     * Spring Web环境中获取HttpServletRequest对象
     *
     * @return HttpServletRequest对象
     */
    public static HttpServletRequest getServletRequest() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    }

    /**
     * Spring Web环境中获取HttpServletRequest对象
     *
     * @return HttpServletResponse对象
     */
    public static HttpServletResponse getServletResponse() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
    }

    /**
     * Spring Web环境中获取ServletContext对象
     *
     * @return ServletContext对象
     */
    public static ServletContext getServletContext() {
        return Objects.requireNonNull(ContextLoader.getCurrentWebApplicationContext()).getServletContext();
    }

    /**
     * Spring Web环境中获取ContextPath应用上下文路径
     *
     * @return 应用上下文路径
     */
    public static String getContextPath() {
        return getServletContext().getContextPath();
    }

    /**
     * 获取指定类的指定方法名的所有参数的名称数组
     *
     * @param clazz      指定的类
     * @param methodName 指定类中的方法
     * @return 方法参数名组成的数组
     */
    public static String[] getParamNames(Class<?> clazz, String methodName) {
        ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                return parameterNameDiscoverer.getParameterNames(method);
            }
        }
        return null;
    }

    /**
     * 获取指定类的指定方法名的所有参数及参数值的Map，key为参数名，value为参数值对象
     *
     * @param clazz
     * @param methodName
     * @param paramArray
     * @return
     */
    public static Map<String, Object> getParamValues(Class<?> clazz, String methodName, Object[] paramArray) {
        String[] argsNames = getParamNames(clazz, methodName);
        if (Objects.isNull(argsNames)) {
            return null;
        }
        int len = argsNames.length;
        Map<String, Object> paramValues = new HashMap<>(len);
        for (int i = 0; i < len; i++) {
            paramValues.put(argsNames[i], paramArray[i]);
        }
        return paramValues;
    }
}
